/*package com.contact.dao.impl; //NOPMD

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;

import org.apache.catalina.users.AbstractUser;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Disjunction;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.joda.time.DateTime;
import org.springframework.dao.support.DataAccessUtils;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.contact.dao.BaseDAO;
import com.contact.util.Utils;
import com.sun.corba.se.spi.ior.Identifiable;

*//**
 * A base class which handles common DAO calls.
 * 
 * @param <T>
 *//*
@SuppressWarnings("unchecked")
public abstract class HibernateBaseDAO<T> extends HibernateDaoSupport implements BaseDAO<T> { //NOPMD
    protected static final String HQL_FROM = "from ";
    protected static final String HQL_SELECTCOUNTFROM = "select count(*) " + HQL_FROM;
    protected static final String HQL_WHERE = " t where t.";
    private final static String FIELD_CUSTOMER = "customer";
    
    private static final String UNNAMED_PROCESS = "Unnamed Process";

    protected transient final String beanName;
    private transient final Class<T> beanClass;
    //private transient final ResultItemSort defaultSort;

    //private transient HibernateSearchProcessor searchProcessor;

    public HibernateBaseDAO(final Class<T> beanClass) {
        super();
        this.beanName = beanClass.getSimpleName();
        this.beanClass = beanClass;
        //this.defaultSort = new ResultItemSort(Identifiable.FIELD_ID, true);
    }

    @Override
    public Class<T> getType() {
        return beanClass;
    }

    protected HibernateSearchProcessor getSearchProcessor() {
        if (searchProcessor == null) {
            searchProcessor = HibernateSearchProcessor.getInstanceForSessionFactory(getSessionFactory());
        }
        return searchProcessor;
    }

    @Override
    public <RT> List<RT> search(ISearch initSearch) {
            ISearch search = this.getSearch(initSearch);
            return search.getSearchClass() == null ? getSearchProcessor().search(super.getSession(), beanClass, search)
                    : getSearchProcessor().search(super.getSession(), search);
    }

    @Override
    public int count(ISearch initSearch, AbstractUser user) {
        ISearch search = this.getSearch(initSearch);
        return search.getSearchClass() == null ? getSearchProcessor().count(super.getSession(), beanClass, search)
                : getSearchProcessor().count(super.getSession(), search);
    }

    @Override
    public <RT> SearchResult<RT> searchAndCount(ISearch initSearch) {
            ISearch search = this.getSearch(initSearch);
            return search.getSearchClass() == null ? getSearchProcessor().searchAndCount(super.getSession(), beanClass, search)
                    : getSearchProcessor().searchAndCount(super.getSession(), search);
    }
    
    @Override
    public <RT> SearchResult<RT> searchAndCount(ISearch search, Redi2User user, Customer customer) {
        ((Search) search).addFilterEqual(FIELD_CUSTOMER, customer);
        return this.searchAndCount(search);
    }

    private ISearch getSearch(ISearch search) {
        if (search == null) {
            return new Search();
        }
        return search;
    }

    @Override
    public T persist(T bean) {
        if (bean.isNew()) {
            bean.setCreatedByUserId(user.getId());
            bean.setCreationDateTime(new DateTime());
        }
        
        bean.setLastUpdatedBy((int) user.getId());
        bean.setLastUpdateDateTime(new DateTime());
        
         if (bean.getLastUpdatingProcess() == null) {
             bean.setLastUpdatingProcess(UNNAMED_PROCESS);
         }
         
        super.getHibernateTemplate().saveOrUpdate(bean);
        return bean;
    }

    @Override
    public T merge(final T bean) {
        if (bean.isNew()) {
            bean.setCreatedByUserId(user.getId());
            bean.setCreationDateTime(new DateTime());
        }

        bean.setLastUpdatedBy((int) user.getId());
        bean.setLastUpdateDateTime(new DateTime());
        
         if (bean.getLastUpdatingProcess() == null) {
             bean.setLastUpdatingProcess(UNNAMED_PROCESS);
         }

         return super.getHibernateTemplate().merge(bean);
    }

    @Override
    public void delete(final T bean) {
        getHibernateTemplate().delete(bean);
    }

    @Override
    public void deleteAll(final Collection<T> all) {
        deleteAll(all);
    }

    protected void deleteAll(final Collection<T> all) {
        getHibernateTemplate().deleteAll(all);
    }

    @Override
    public void deleteById(final long id, AbstractUser user) {
        T bean = getById(id);
        if (bean != null) {
            delete(bean);
        }
    }

    @Override
    public void deleteByIds(final Set<Long> ids, AbstractUser user) {
        List<T> list = getAllByIds(ids);
        if (Utils.hasValues(list)) {
            deleteAll(list, user);
        }
    }

    @Override
    public T getById(final long id) {
        return getById(beanClass, id);
    }

    @Override
    public <B> B getById(Class<B> clazz, final long id) {
        return getHibernateTemplate().get(clazz, id);
    }

    @Override
    public List<T> getAllByIds(final Set<Long> ids) {
        if (Utils.isEmpty(ids)) {
            return null;
        }
        DetachedCriteria criteria = getCriteria(false);
        criteria.add(Restrictions.in(Identifiable.FIELD_ID, ids));
        return getAllByCriteria(criteria, true);
    }

    @Override
    public T getByAttribute(final String attribute, final Object value) {
        return DataAccessUtils.uniqueResult(getAllByAttribute(attribute, value));
    }

    @Override
    public T getByAttributes(final String[] attributes, final Object[] values) {
        return DataAccessUtils.uniqueResult(getAllByAttributes(attributes, values));
    }

    @Override
    public List<T> getAllByAttribute(final String attribute, final Object value) {
        String[] attributes = { attribute };
        Object[] values = { value };
        return getAllByCriteria(createCriteria(attributes, values, true), true);
    }

    @Override
    public List<T> getAllByAttributes(String[] attributes, Object[] values) {
        return getAllByCriteria(createCriteria(attributes, values, true), true);
    }

    @Override
    public List<T> getAllByOrAttributes(String[] attributes, Object[] values) {
        return getAllByCriteria(createOrCriteria(attributes, values, true), true);
    }

    @Override
    public int getCountByAttributes(String[] attributes, Object[] values) {
        return getCountByCriteria(createCriteria(attributes, values, true));
    }

    private DetachedCriteria createOrCriteria(String[] attributes, Object[] values, boolean filterDeleted) {
        DetachedCriteria criteria = getCriteria(filterDeleted);
        Disjunction disjunction = Restrictions.disjunction();
        for (int i = 0; i < attributes.length; i++) {
            Object value = values[i];
            String attr = attributes[i];
            disjunction.add(CriterionHelper.getCriterion(attr, value));
        }
        criteria.add(disjunction);
        return criteria;
    }

    private DetachedCriteria createCriteria(String[] attributes, Object[] values, boolean filterDeleted) {
        DetachedCriteria criteria = getCriteria(filterDeleted);
        for (int i = 0; i < attributes.length; i++) {
            Object value = values[i];
            String attr = attributes[i];
            criteria.add(CriterionHelper.getCriterion(attr, value));
        }
        return criteria;
    }

    protected List<T> getAllByCriteria(DetachedCriteria criteria, boolean removeDuplicates) {
        if (removeDuplicates) {
            return Utils.removeDuplicates(getHibernateTemplate().findByCriteria(criteria));
        }
        return getHibernateTemplate().findByCriteria(criteria);
    }

    protected T getByCriteria(DetachedCriteria criteria) {
        return (T) DataAccessUtils.uniqueResult(getHibernateTemplate().findByCriteria(criteria));
    }

    protected int getCountByCriteria(DetachedCriteria criteria) {
        criteria.setProjection(Projections.rowCount());
        List<Long> longList = getHibernateTemplate().findByCriteria(criteria);
        if (Utils.isEmpty(longList)) {
            return 0;
        }
        return longList.get(0).intValue();
    }

    protected DetachedCriteria getCriteria(boolean filterDeleted) {
        return DetachedCriteria.forClass(beanClass);
    }

    @Override
    public List<T> getAll() {
        return getAllByCriteria(getCriteria(true), true);
    }

    @Override
    public void saveAll(Collection<T> all, AbstractUser user) {
        if(Utils.isEmpty(all)) {
            return;
        }

        for(T t : all) {
            if(t.isNew()) {
                t.setCreatedByUserId(user.getId());
                t.setCreationDateTime(new DateTime());
            }

            t.setLastUpdatedBy((int) user.getId());
            t.setLastUpdateDateTime(new DateTime());
            
             if(t.getLastUpdatingProcess() == null) {
                 t.setLastUpdatingProcess(UNNAMED_PROCESS);
             }
        }

        super.getHibernateTemplate().saveOrUpdateAll(all);
    }

    @Override
    public List<T> getAll(IPaginationInfo pageInfo) {
        return getPageOfData(getCriteria(true), pageInfo);
    }

    protected List<T> getPageOfData(DetachedCriteria criteria, IPaginationInfo pageInfo) {
        if (pageInfo == null) {
            return getAllByCriteria(criteria, true);
        }
        criteria.getExecutableCriteria(getSession()).setFirstResult(pageInfo.getFirstRow());
        criteria.getExecutableCriteria(getSession()).setMaxResults(pageInfo.getMaxResults());
        addOrder(criteria, pageInfo);
        criteria.setProjection(Projections.distinct(Projections.id()));
        List<Long> list = getHibernateTemplate().findByCriteria(criteria);

        if (Utils.isEmpty(list)) {
            return new ArrayList<T>();
        }

        DetachedCriteria crit = getCriteria(false);
        addOrder(crit, pageInfo);
        crit.add(Restrictions.in(T.FIELD_ID, list));
        return getAllByCriteria(crit, true);
    }

    public <B> List<B> getByNamedSQLQuery(final String queryName, final String params[], final Object values[],
            final IPaginationInfo pageInfo) {
        return getPageOfData(queryName, params, values, pageInfo, true, true);
    }

    @Override
    public <B> List<B> getByNamedQuery(final String queryName, final String params[], final Object values[],
            final IPaginationInfo pageInfo) {
        return getPageOfData(queryName, params, values, pageInfo, true, false);
    }

    @Override
    public T getByNamedQuery(final String queryName, final String params[], final Object values[]) {
        List<T> list = this.getPageOfData(queryName, params, values, null, true, false);
        if(Utils.isEmpty(list)) {
            return null;
        }
        return list.get(0);
    }

    @Override
    public <B> List<B> getByStringQuery(final String queryStr, final String params[], final Object values[]) {
        return getPageOfData(queryStr, params, values, null, false, false);
    }

    @Override
    public <B> List<B> getByStringQuery(final String queryStr, final String params[], final Object values[],
            final IPaginationInfo pageInfo) {
        return getPageOfData(queryStr, params, values, pageInfo, false, false);
    }

    private <B> List<B> getPageOfData(final String queryStr, final String params[], final Object values[], //NOPMD
            final IPaginationInfo pageInfo, final boolean namedQuery, final boolean isSQL) {
        return this.getHibernateTemplate().executeFind(new HibernateCallback<List<B>>() {
            @Override
            public List<B> doInHibernate(Session session) {//NOPMD
                Query q = namedQuery ? session.getNamedQuery(queryStr) : session.createQuery(queryStr);
                if (pageInfo != null) {
                    ResultItemSort ris = pageInfo.getResultItemSort();

                    if (ris != null && ris.hasSort()) {
                        // This assumes matching hql variable name assigned in front of sortable column.
                        // Therefore, sorting on the "number" column of Payee gets forced to look like this -> payee.number.
                        String query = String.format("%s order by %s %s", q.getQueryString(), isSQL ? ris.getColumn()
                                : getStandardHQLVariableName(beanClass, ris.getColumn()), ris.getAscending() ? "asc"
                                : "desc");
                        q = isSQL ? session.createSQLQuery(query) : session.createQuery(query);
                    }
                    q.setFirstResult(pageInfo.getFirstRow());
                    q.setMaxResults(pageInfo.getMaxResults());
                }
                if (params != null) {
                    for (int i = 0; i < params.length; i++) {
                        if (values[i] instanceof Collection) {
                            q.setParameterList(params[i], (Collection<B>) values[i]);
                        } else {
                            q.setParameter(params[i], values[i]);
                        }
                    }
                }
                return q.list();
            }
        });
    }

    private String getStandardHQLVariableName(final Class<?> clazz, final String sortColumn) {
        String name = clazz.getSimpleName();
        return Character.toLowerCase(name.charAt(0)) + (name.length() > 1 ? name.substring(1) : "") + "." + sortColumn;
    }

    protected DetachedCriteria addOrder(DetachedCriteria criteria, IPaginationInfo pageInfo) {
        ResultItemSort ris = pageInfo.getResultItemSort();
        if (ris != null && ris.hasSort()) {
            addOrder(criteria, ris);
        } else {
            addDefaultOrder(criteria);
        }
        return criteria;
    }

    protected DetachedCriteria addOrder(DetachedCriteria criteria, ResultItemSort ris) {
        if (ris.getAscending()) {
            criteria.addOrder(Order.asc(ris.getColumn()));
        } else {
            criteria.addOrder(Order.desc(ris.getColumn()));
        }
        return criteria;
    }

    protected DetachedCriteria addDefaultOrder(DetachedCriteria criteria) {
        return addOrder(criteria, defaultSort);
    }

    @SuppressWarnings("rawtypes")
    protected long count(DetachedCriteria criteria) {
        criteria.setProjection(Projections.rowCount());
        List list = getHibernateTemplate().findByCriteria(criteria);
        if (list == null || list.isEmpty()) {
            return 0;
        }
        return (Long) list.get(0);
    }

    *//**
     * This is a much better implementation of paginated query by criteria than the one found in HibernateBaseDAO but it
     * assumes that the query is such that it returns unique results.
     *//*
    protected List<T> getAllByCriteria(DetachedCriteria criteria, IPaginationInfo pageInfo) {
        if (pageInfo == null) {
            return getAllByCriteria(criteria, true);
        }
        criteria.getExecutableCriteria(getSession()).setFirstResult(pageInfo.getFirstRow());
        criteria.getExecutableCriteria(getSession()).setMaxResults(pageInfo.getMaxResults());
        addOrder(criteria, pageInfo);
        return getHibernateTemplate().findByCriteria(criteria);
    }
    
}
*/